package com.sky.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.PasswordConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.EmployeeDTO;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.entity.Employee;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.result.PageResult;
import com.sky.service.EmployeeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.List;

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();

        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        //密码比对
        // 对前端传过来的密码进行MD5加密后再比对
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (employee.getStatus() == StatusConstant.DISABLE) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }

    /**
     * 新增员工
     * @param employeeDTO
     */
    @Override
    public void save(EmployeeDTO employeeDTO) {
        // 因为他是一个VTO 所以将他转换成一个Java对象然后进行操作更方便
        // 然后在这里也可以将一些没有设置的值进行设置
        // 这里可以采用拷贝的方式 拷贝有一个要求
        // 就是二者对象中的属性必须一样 当时拷贝到的对象可以属性比被拷贝的多
        Employee employee = new Employee();
        // 第一个是被拷贝对象 第二个是拷贝到的对象
        BeanUtils.copyProperties(employeeDTO,employee);

        // 密码也是设置成一个默认值 123456 先 后期登陆后可以修改
        // 并且存入的是MD5加密后的 因为MD5是不可逆的 所以判断也是用先转成MD5再判断
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));

        // 对于状态有封装到一个软件包内专门有一堆常量 其中有一个状态
        // 然后设置这里面 可以解决硬编码问题
        // 这里设置成可以访问 ENABLE : 1
        employee.setStatus(StatusConstant.ENABLE);

        // 创建时间和修改时间都是当前的时间
//        employee.setCreateTime(LocalDateTime.now());
//        employee.setUpdateTime(LocalDateTime.now());

        // 设置用户和修改用户的id 都是先临时设置一个固定 的
        // 从线程中获取到保存的ID
//        employee.setCreateUser(BaseContext.getCurrentId());
//        employee.setUpdateUser(BaseContext.getCurrentId());

        // 然后将数据插入到数据库 用Mapper
        employeeMapper.insert(employee);
    }

    /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    // EmployeePageQueryDTO: 里面封装的是页码还有每页的记录数存在List里面
    // 这里是用SpringMVC的自动装配到这 因为它是路径参数 所以自己会接收
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO){
        // 开始分页
        // 获取当前页码和总页码
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());

        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);

        long total = page.getTotal();
        List<Employee> records = page.getResult();

        return new PageResult(total,records);
    }

    /**
     * 启用禁用员工账号
     * @param status
     * @param id
     */
    public void startOrStop(Integer status, Long id) {
        // 这启用禁用本质上是一个修改的SQL 也就是修改员工的每一个字段
        // 希望执行语句是 update employ set status = ? where id = ?
        // 为了让它有通用性 未来修改员工什么的 所以希望把update修改成动态的
        // 也就是不只是修改status 和 id 而是根据传进来参数不同 修改多个字段
        // 所以这时候需要用到实体类 这样子即使这里只是修改status 但是如果修改员工信息
        // 就可以还是用这个update

        // 创建实体类
        // 传统创建如下 然后用set
//        Employee employee = new Employee();

        // 也可以用builder (前提类有带这个注解)
        Employee employee = Employee.builder()
                        .status(status)
                        .id(id)
                        .build();

        employeeMapper.update(employee);
    }

    /**
     * 查询员工信息
     * @param id
     * @return
     */
    public Employee getById(Long id) {
        Employee employee = employeeMapper.getById(id);
        employee.setPassword("密码不能给你看");
        return employee;
    }

    /**
     * 编辑员工信息
     * @param employeeDTO
     */
    public void update(EmployeeDTO employeeDTO) {
        // 这里需要将这个DTO进行转换到employee 符合我们所编写的实体类
        // 因为update 就是根据employee 进行制作的动态SQL
        // 而这个DTO 是根据前端所可以传来的参数而制作出来的 抽取出
        // employee一部分属性
        Employee employee = new Employee();
        // 第一个是被拷贝参数,第二个是拷贝到的参数
        BeanUtils.copyProperties(employeeDTO,employee);
        // 这里修改时间直接设置为当前的系统时间
//        employee.setUpdateTime(LocalDateTime.now());
        // 因为前面进行了id的设置 所以这里直接获取到id即可
//        employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.update(employee);
    }

}
